package com.weixing.mall.provider.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.weixing.mall.base.constant.DatePattern;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.enums.IdGenTagEnum;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.enums.WhetherEnum;
import com.weixing.mall.provider.mapper.OutDepotBillMapper;
import com.weixing.mall.provider.mapper.OutDepotBillProductMapper;
import com.weixing.mall.provider.mapper.ProductStockMapper;
import com.weixing.mall.provider.model.domain.*;
import com.weixing.mall.provider.model.dto.OutDepotBillDto;
import com.weixing.mall.provider.model.dto.OutDepotBillProductDto;
import com.weixing.mall.provider.model.dto.OutDepotChgIsFinishDto;
import com.weixing.mall.provider.model.query.DepotBillDetilQuery;
import com.weixing.mall.provider.model.query.OutDepotBillQuery;
import com.weixing.mall.provider.model.vo.OutDepotBillProductDetilVo;
import com.weixing.mall.provider.model.vo.OutDepotBillVo;
import com.weixing.mall.provider.service.IDefectiveProductService;
import com.weixing.mall.provider.service.IDepotService;
import com.weixing.mall.provider.service.IOutDepotBillService;
import com.weixing.mall.provider.service.IProductStockDetailsService;
import com.weixing.mall.provider.util.DepotUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 仓库模块-调货出库单 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-15
 */
@Service
public class OutDepotBillServiceImpl extends ServiceImpl<OutDepotBillMapper, OutDepotBill> implements IOutDepotBillService {

    @Autowired
    private OutDepotBillProductMapper outDepotBillProductMapper;
    @Autowired
    private ProductStockMapper productStockMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IProductStockDetailsService productStockDetailsService;
    @Autowired
    private IDefectiveProductService defectiveProductService;
    @Autowired
    private IDepotService depotService;


    @Override
    public IPage selectOfPage(Page page, OutDepotBillQuery outDepotBillQuery) {
        return baseMapper.selectOfPage(page, outDepotBillQuery);
    }

    @Override
    public IPage<OutDepotBillProductDetilVo> getOutDepotBillDetilList(Page page, DepotBillDetilQuery depotBillDetilQuery) {
        return outDepotBillProductMapper.getOutDepotBillDetilList(page, depotBillDetilQuery);
    }

    @Override
    public long save(OutDepotBillDto outDepotBillDto, Long uid) {
        OutDepotBill outDepotBill = new OutDepotBill();
        BeanUtils.copyProperties(outDepotBillDto, outDepotBill);
        if (null != outDepotBillDto.getOutDepotType()) {
            outDepotBill.setOutDepotType(outDepotBillDto.getOutDepotType().getValue());
        }
        Long outDepotId = outDepotBillDto.getId();
        outDepotBill.setIsFinish(outDepotBillDto.getIsFinish().getValue());
        if (null == outDepotBillDto.getId()) {
            outDepotBill.setCreatedBy(uid);
            outDepotBill.setBillSn(outDepotBillDto.getBillSn());
            if (outDepotBill.getIsFinish().equals(WhetherEnum.YES.getValue())) {
                outDepotBill.setOutDepotTime(new Date());
            }
            //保存出库单
            baseMapper.insert(outDepotBill);
            //出库单id
            outDepotId = outDepotBill.getId();
            if (outDepotBillDto.getProducts().size() > 0) {
                //出库单相关连商品list
                List<OutDepotBillProductDto> list = outDepotBillDto.getProducts();
                for (int i = 0; i < list.size(); i++) {
                    OutDepotBillProductDto outDepotBillProductDto = list.get(i);
                    OutDepotBillProduct outDepotBillProduct = new OutDepotBillProduct();
                    BeanUtils.copyProperties(outDepotBillProductDto, outDepotBillProduct);
                    if(ObjectUtil.isNull(outDepotBillProductDto.getStockSn())){
                        ProductStockDetails details=productStockDetailsService.getById(outDepotBillProductDto.getStockId());
                        if(ObjectUtil.isNotNull(details)){
                            outDepotBillProduct.setStockSn(details.getStockSn());
                        }
                    }
                    outDepotBillProduct.setCreatedBy(uid);
                    //关联商品添加出库单id
                    outDepotBillProduct.setOutDepotId(outDepotBill.getId());
                    //保存关联商品
                    outDepotBillProductMapper.insert(outDepotBillProduct);
                }
            }

        } else {
            outDepotBill.setUpdatedBy(uid);
            outDepotBill.setUpdatedTime(new Date());
            if (outDepotBill.getIsFinish().equals(WhetherEnum.YES.getValue())) {
                outDepotBill.setOutDepotTime(new Date());
            }
            //修改出库单
            baseMapper.updateById(outDepotBill);
            if (outDepotBillDto.getProducts().size() > 0) {
                //出库单相关连商品list
                List<OutDepotBillProductDto> list = outDepotBillDto.getProducts();
                outDepotBillProductMapper.delete(new QueryWrapper<OutDepotBillProduct>().eq("out_depot_id", outDepotId));
                for (int i = 0; i < list.size(); i++) {
                    OutDepotBillProductDto outDepotBillProductDto = list.get(i);
                    OutDepotBillProduct outDepotBillProduct = new OutDepotBillProduct();
                    BeanUtils.copyProperties(outDepotBillProductDto, outDepotBillProduct);
                    outDepotBillProduct.setCreatedBy(uid);
                    //关联商品添加出库单id
                    outDepotBillProduct.setOutDepotId(outDepotId);
                    //保存关联商品
                    outDepotBillProductMapper.insert(outDepotBillProduct);
                }
            }
        }
        return outDepotId;
    }

    @Override
    public void outDepotChgIsFinish(OutDepotChgIsFinishDto outDepotChgIsFinishDto) {
        outDepotChgIsFinishDto.setOutDepotTime(new Date());
        baseMapper.outDepotChgIsFinish(outDepotChgIsFinishDto);
    }

    @Override
    public OutDepotBillVo getOutDepotBillById(Long id) {
        return baseMapper.getOutDepotBillById(id);
    }

    @Override
    public OutDepotBillVo findMaxId() {
        OutDepotBillVo vo = baseMapper.findMaxId();
        if (vo == null) {
            vo = new OutDepotBillVo();
            vo.setId(1L);
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public void saveAndAuit(OutDepotBillDto outDepotBillDto, Long uid) {
        outDepotBillDto.setIsFinish(WhetherEnum.YES);
        save(outDepotBillDto, uid);
        List<OutDepotBillProductDto> products = outDepotBillDto.getProducts();
       /* for (OutDepotBillProductDto dto : products) {
            ProductStock stock = productStockMapper.selectOne(new QueryWrapper<ProductStock>().eq("depot_id", outDepotBillDto.getOutputDepot()).eq("product_id", dto.getProductId()));
            int depotStock = 0;
            int enableStock = 0;
            depotStock = stock.getStock() - dto.getQuantity();
            enableStock = stock.getEnableStock() - dto.getQuantity();
            if (depotStock < 0 || enableStock < 0) {
                throw new BusinessException("库存不允许小于0，不允许出库");
            }
            stock.setStock(depotStock);
            stock.setEnableStock(enableStock);
            productStockMapper.updateById(stock);
            ProductStock stockcheck = productStockMapper.selectOne(new QueryWrapper<ProductStock>().eq("depot_id", outDepotBillDto.getOutputDepot()).eq("product_id", dto.getProductId()));
            if (stockcheck.getStock() < 0 || stockcheck.getEnableStock() < 0) {
                throw new BusinessException("库存不允许小于0，不允许出库");
            }
        }*/

        //二期对于是次品库的进行操作
        Depot depot=depotService.getById(outDepotBillDto.getOutputDepot());
        if(depot.getIsDefective().intValue()==WhetherEnum.YES.getValue().intValue()){//如果为次品库，则次品库数据进行梳理
            goOutDefective(products,uid);
        }else{
            // 二期库存进行优化，执行批量删除操作
            goProductDetails(products);
        }


    }

    /**
     * 次品库出库操作。
     * @param products
     * @param uid
     */
    private void goOutDefective(List<OutDepotBillProductDto> products, Long uid) {
        for(OutDepotBillProductDto outDepotBillProductDto :products){
            defectiveProductService.removeById(outDepotBillProductDto.getStockId());
        }

    }

    /**
     * 二期项目，批量出库存模块
     * @param products
     */
    private void goProductDetails(List<OutDepotBillProductDto> products) {
        int splitNumber = products.size() / GlobalConstant.BATCH_SIZE + 1;
        List<List<OutDepotBillProductDto>> splitList = Lists.partition(products, splitNumber);
        for (List<OutDepotBillProductDto> list : splitList) {
           /* List<ProductStockDetails> insertBathList = Lists.newArrayList();
            for (OutDepotBillProductDto inDepotBillProductDto : list) {
                ProductStockDetails productStockDetails = new ProductStockDetails();
                productStockDetails.setId(inDepotBillProductDto.getStockId());
                insertBathList.add(productStockDetails);
            }*/
            List<Long> idList=list.stream().map(OutDepotBillProductDto::getStockId).collect(Collectors.toList());
            productStockDetailsService.removeByIds(idList);
        }
    }

    @Override
    public String getOutBillSn(String prefix) {
        long liveTime = 86400L;
        String dateFmt = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
        String key = IdGenTagEnum.DEPOT_OUT_SN_REDIS.getValue() + dateFmt;
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        String result = DepotUtil.genTransBillSn(prefix, dateFmt, increment + 1);
        return result;

    }

}
